package user_accounts

import (
	"gitee.com/theegg/go-brick/app/model"
	"gitee.com/theegg/go-brick/app/model/user/user_account_flow_reports"
	"gitee.com/theegg/go-brick/app/service/app"
	"strconv"
	"time"
)

// 查询参数
type UserAccountQueryParams struct {
	PageSize  string `form:"page_size" json:"page_size"  binding:"gte=0,lte=100" label:"每页数量"`
	PageIndex string `form:"page_index" json:"page_index"  binding:"gte=0,lte=99999" label:"当前页数"`
	UserName  string `form:"username" json:"username"  binding:"" label:"用户名"`
}

// 添加参数
type UserAccountAddParams struct {
	Score string `form:"score"  binding:"gte=1,max=100000" label:"积分"`
}

// 分页获取所有数据
// @param params map 参数
// @return interface{}, error
func GetDataList(params map[string]interface{}) (map[string]interface{}, error) {
	returnData := make(map[string]interface{}, 0)

	queryParams, err := model.BuildAdminQueryParam(params)
	if err != nil {
		return returnData, nil
	}

	query := app.Db().Desc("id").Limit(queryParams.Limit, queryParams.Offset)

	// 查询用户名 == username
	if queryParams.Params["username"] != "" {
		query.Where("username = ?", queryParams.Params["username"])
	}

	nodeData := make([]UserAccounts, 0)

	// 求总条数
	total, err := query.FindAndCount(&nodeData)
	if err != nil {
		return nil, app.NewError(err)
	}

	returnData["data"] = nodeData
	returnData["total"] = total

	return returnData, nil
}

// 获取单个数据
// @title GetAccountByUserId
// @return *Users, error
func GetAccountByUserId(userId int64) (*UserAccounts, error) {
	item := new(UserAccounts)
	has, err := app.Db().Where("user_id = ?", userId).Get(item)

	if err != nil {
		return nil, app.NewError(err)
	} else {
		if !has {
			return nil, app.NewError("对不起, 不存在的用户账户")
		}
	}

	return item, nil
}

// 是否存在用户
func (ua UserAccounts) HasUserFromName(username string) bool {
	user := new(UserAccounts)

	has, err := app.Engine.Where("username = ?", username).Get(user)

	if err != nil {
		app.Log().Error(err)
		return false
	} else {
		if !has {
			return false
		}
	}

	return true
}

/** ==================== 流转包装 ===================== */

// @title 添加金币
// @description 添加金币
func (ua *UserAccounts) DoFinanceUserAddCoin(params map[string]interface{}) error {
	flowParams := map[string]interface{}{
		"amount":  params["amount"],
		"user_id": ua.UserId,
	}

	return ua.DoCoinFlow(10101, flowParams)
}

// @title 理赔金币 增加
// @description 理赔金币
func (ua *UserAccounts) DoFinanceAdminAddCoin(params map[string]interface{}) error {
	flowParams := map[string]interface{}{
		"amount":        params["amount"],
		"user_id":       ua.UserId,
		"from_admin_id": params["from_admin_id"],
	}

	return ua.DoCoinFlow(10102, flowParams)
}

// @title 理赔金币 扣除
// @description 理赔金币
func (ua *UserAccounts) DoFinanceAdminReduceCoin(params map[string]interface{}) error {
	flowParams := map[string]interface{}{
		"amount":        params["amount"],
		"user_id":       ua.UserId,
		"from_admin_id": params["from_admin_id"],
	}

	if ua.Balance < params["amount"].(int64) {
		return app.NewError("sorry, left balance is not enough")
	}

	return ua.DoCoinFlow(20102, flowParams)
}

// @title 购买商品
// @description 购买商品
func (ua *UserAccounts) DoFinanceUserBuy(params map[string]interface{}) error {
	flowParams := map[string]interface{}{
		"amount":  params["amount"],
		"user_id": ua.UserId,
	}

	return ua.DoCoinFlow(10101, flowParams)
}

// @title 理赔积分
// @description 理赔积分
func (ua *UserAccounts) DoFinanceAdminAddScore(params map[string]interface{}) error {
	flowParams := map[string]interface{}{
		"amount":        params["amount"],
		"user_id":       ua.UserId,
		"from_admin_id": params["from_admin_id"],
	}

	return ua.DoCoinFlow(10901, flowParams)
}

// ===========  账户锁(分布式)  ==========
// ===========  账户锁(分布式)  ==========
func (ua *UserAccounts) DoCoinFlow(flowId int, params map[string]interface{}) error {
	if _, ok := AccountFlowType[flowId]; !ok {
		return app.NewError("invalid flow type!")
	}

	item := AccountFlowType[flowId]
	paramOptions := item["require"]

	for field, v := range paramOptions.(map[string]bool) {
		if _, ok := params[field]; !ok && v {
			return app.NewError("params " + field + " not exist!")
		}
	}

	// 锁
	locker := app.RedisLocker()
	mutex := locker.NewMutex("user-locker-" + strconv.FormatInt(ua.Id, 10))
	if err := mutex.Lock(); err != nil {
		return app.NewError("sorry, lock failed")
	}

	defer mutex.Unlock()

	beforeBalance := ua.Balance
	beforeLockedBalance := ua.LockedBalance

	// 添加
	if item["flow_type"] == "in" {
		ua.Balance += params["amount"].(int64)
	} else {
		ua.Balance -= params["amount"].(int64)
	}

	// 更新账户
	var errUpdate error
	var affected int64
	affected, errUpdate = app.Db().Table(new(UserAccounts)).ID(ua.Id).Cols("balance").Update(map[string]int64{"balance": ua.Balance})

	if errUpdate != nil {
		return app.NewError(errUpdate)
	}

	// 生效条数
	if affected == 0 {
		return app.NewError("对不起, 指定的ID更新数量不正确")
	}

	// 更新日志
	logData := new(user_account_flow_reports.UserAccountFlowReports)

	logData.UserId = ua.UserId
	logData.Username = ua.Username
	logData.Pid = ua.Pid
	logData.Tid = ua.Tid

	logData.FlowType = item["flow_type"].(string)
	logData.TypeId = item["id"].(int)
	logData.TypeName = item["name"].(string)

	logData.Amount = params["amount"].(int64)

	logData.BeforeBalance = beforeBalance
	logData.Balance = ua.Balance
	logData.BeforeLockedBalance = beforeLockedBalance
	logData.LockedBalance = ua.LockedBalance

	logData.UserId = ua.UserId
	logData.UserId = ua.UserId

	logData.ProcessTime = time.Now().Unix()

	// 插入数据
	affected, errInsert := app.Db().Insert(logData)
	if errInsert != nil {
		return app.NewError(errInsert)
	}

	if affected != 1 {
		return app.NewError("sorry, insert account flow log fail(wrong number item insert)!")
	}

	return nil
}
